﻿using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ricebird.Wordprocessing
{
    public class WordParagraph : CompositeElementBase
    {
        private Paragraph Paragraph
        {
            get; set;
        }

        private ParagraphProperties Properties
        {
            get; set;
        }

        private RunProperties DefaultRunProperties
        {
            get; set;
        }

        #region ctor
        internal WordParagraph(Paragraph para, CompositeElementBase parent)
            : base(parent)
        {
            Paragraph = para;
            InitializeElement();
        }

        internal WordParagraph(Paragraph para, WordDocument doc)
            : base(doc)
        {
            Paragraph = para;
            InitializeElement();
        }

        public override void InitializeElement()
        {
            Properties = Paragraph.GetFirstChild<ParagraphProperties>();
            if (Properties == null)
            {
                Properties = new ParagraphProperties();
                Paragraph.PrependChild(Properties);
            }

            DefaultRunProperties = new RunProperties();
        }
        #endregion

        #region 添加连续文本
        public override CompositeElementBase Append(string text)
        {
            return Append(text, Document.DefaultStyle);
        }

        public override CompositeElementBase Append(string text, WordStyles style)
        {
            var para = Paragraph;
            Run r = new Run();
            r.RunProperties = DefaultRunProperties;
            para.Append(r);
            WordRun wr = new WordRun(r, this);
            Children.Add(wr);
            wr.SetText(text);
            wr.SetStyle(style);
            return wr;
        }
        #endregion

        #region 设置格式
        public override CompositeElementBase SetFontFamily(string family)
        {
            return SetFontFamily(family, family);
        }

        public override CompositeElementBase SetFontFamily(string zwFamily, string asciiFamily)
        {
            DefaultRunProperties.RunFonts = new RunFonts()
            {
                Ascii = asciiFamily,
                EastAsia = zwFamily
            };
            return SetPropertiesToChildren();
        }

        public override CompositeElementBase SetFontSize(int sizePoint)
        {
            if (sizePoint < 0 || sizePoint > 800)
            {
                throw new InvalidOperationException("字体大小必须大于0，并且小于800");
            }

            DefaultRunProperties.FontSize = new DocumentFormat.OpenXml.Wordprocessing.FontSize()
            {
                Val = (sizePoint * 2).ToString()
            };
            return SetPropertiesToChildren();
        }

        public override CompositeElementBase SetFontSize(FontSize size)
        {
            int sz = (int)size;
            DefaultRunProperties.FontSize = new DocumentFormat.OpenXml.Wordprocessing.FontSize()
            {
                Val = sz.ToString()
            };
            return SetPropertiesToChildren();
        }

        public override CompositeElementBase SetBold(bool isBold = true)
        {
            DefaultRunProperties.Bold = new Bold()
            {
                Val = new OnOffValue(isBold)
            };
            return SetPropertiesToChildren();
        }

        public override CompositeElementBase SetItalic(bool isItalic = true)
        {
            DefaultRunProperties.Italic = new Italic()
            {
                Val = new OnOffValue(isItalic)
            };
            return SetPropertiesToChildren();
        }

        public override CompositeElementBase SetUnderline(UnderlineStyle lineStyle = UnderlineStyle.Single)
        {
            UnderlineValues value = (UnderlineValues)Enum.Parse(typeof(UnderlineValues), lineStyle.ToString());
            DefaultRunProperties.Underline = new Underline()
            {
                Val = value
            };
            return SetPropertiesToChildren();
        }

        public override CompositeElementBase SetAlign(TextAlign align = TextAlign.Left)
        {
            JustificationValues value = (JustificationValues)Enum.Parse(typeof(JustificationValues), align.ToString());
            Properties.Justification = new Justification()
            {
                Val = value
            };

            return this;
        }

        public override CompositeElementBase SetFirstLineIndent(double chars = 2)
        {
            if (chars < 0)
            {
                throw new InvalidOperationException("参数chars必须大于 0");
            }

            Properties.Indentation = Properties.Indentation ?? new Indentation();
            Properties.Indentation.FirstLineChars = (int)(chars * 100);
            return this;
        }

        /// <summary>
        /// 设置左侧缩进字符
        /// </summary>
        /// <param name="chars"></param>
        /// <returns></returns>
        public override CompositeElementBase SetLeftChars(double chars = 0)
        {
            if (chars < 0)
            {
                throw new InvalidOperationException("参数chars必须大于 0");
            }

            Properties.Indentation = Properties.Indentation ?? new Indentation();
            Properties.Indentation.LeftChars = (int)(chars * 100);
            return this;
        }

        /// <summary>
        /// 设置右侧缩进字符
        /// </summary>
        /// <param name="chars"></param>
        /// <returns></returns>
        public override CompositeElementBase SetRightChars(double chars = 0)
        {
            if (chars < 0)
            {
                throw new InvalidOperationException("参数chars必须大于 0");
            }

            Properties.Indentation = Properties.Indentation ?? new Indentation();
            Properties.Indentation.RightChars = (int)(chars * 100);
            return this;
        }

        public override CompositeElementBase SetLineSpacing(double times)
        {
            var sbl = Properties.SpacingBetweenLines;
            if (sbl == null)
            {
                sbl = new SpacingBetweenLines();
                Properties.SpacingBetweenLines = sbl;
            }
            sbl.Line = (times * 240).ToString();
            return this;
        }

        public override CompositeElementBase SpaceingBefore(int pt)
        {
            var sbl = Properties.SpacingBetweenLines;
            if (sbl == null)
            {
                sbl = new SpacingBetweenLines();
                Properties.SpacingBetweenLines = sbl;
            }
            sbl.Before = (pt * 20).ToString();
            return this;
        }

        public override CompositeElementBase SpacingAfter(int pt)
        {
            var sbl = Properties.SpacingBetweenLines;
            if (sbl == null)
            {
                sbl = new SpacingBetweenLines();
                Properties.SpacingBetweenLines = sbl;
            }
            sbl.After = (pt * 20).ToString();
            return this;
        }

        internal void SetProperties(ParagraphProperties prop)
        {
            Properties = prop;
        }

        internal CompositeElementBase SetPropertiesToChildren()
        {
            foreach (var item in Children)
            {
                (item as WordRun)?.SetProperties(DefaultRunProperties);
            }

            return this;
        }
        #endregion

        #region 流式接口 - 设置样式
        protected override CompositeElementBase SetStyleSafe(WordStyles style)
        {
            Properties.ParagraphStyleId = style.ParagraphStyleId;
            foreach (var item in Children)
            {
                (item as WordRun)?.SetStyle(style);
            }

            return this;
        }
        #endregion

        #region 流式接口
        public override CompositeElementBase AppendParagraph()
        {
            return Document.AppendParagraph();
        }

        public override CompositeElementBase AppendParagraph(string text)
        {
            return Document.AppendParagraph(text);
        }

        public override CompositeElementBase AppendParagraph(WordStyles style)
        {
            return Document.AppendParagraph(style);
        }

        public override CompositeElementBase AppendParagraph(string text, WordStyles style)
        {
            return Document.AppendParagraph(text, style);
        }
        #endregion
    }
}
